home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / AMISL083.ARJ / NOTE.ASM < prev    next >
Assembly Source File  |  1992-04-20  |  21KB  |  876 lines

  1. ;-----------------------------------------------------------------------
  2. ; NOTE.ASM    Public Domain 1992 Ralf Brown
  3. ;        You may do with this software whatever you want, but
  4. ;        common courtesy dictates that you not remove my name
  5. ;        from it.
  6. ;
  7. ; Popup to append one or more lines to a text file.  Demonstration of the
  8. ; use of DOS from within an AMIS-compliant TSR.
  9. ; Note: popup may be done from the commandline or via a hotkey; however,
  10. ;     the hotkey support requires a newer BIOS which has the INT 15/4F
  11. ;    keyboard intercept
  12. ;
  13. ; Version 0.81
  14. ; LastEdit: 4/20/92
  15. ;-----------------------------------------------------------------------
  16.  
  17. __TINY__ equ 1                ; using Tiny model
  18.     INCLUDE AMIS.MAC
  19.  
  20. ;-----------------------------------------------------------------------
  21. ;
  22. VERSION_NUM equ 0051h    ; v0.81
  23. VERSION_STR equ "0.81"
  24.  
  25. WINDOW_TOP    equ 0        ; topmost row of TSR's popup window
  26. WINDOW_LEFT   equ 5        ; leftmost column of TSR's popup window
  27. WINDOW_HEIGHT equ 3           ; height (including frame) of popup window
  28. WINDOW_WIDTH  equ 70          ; width (including frame) of popup window
  29. LOCAL_STACK_SIZE equ 128    ; size of local stack in bytes
  30. HOTKEY_SCAN   equ 31h        ; scan code for 'N' key
  31. HOTKEY_NAME   equ "N"
  32.  
  33. ;-----------------------------------------------------------------------
  34. ; Declare our segments in the order we want them in the executable.
  35. ;
  36. _TEXT    SEGMENT PUBLIC BYTE 'CODE'
  37. _TEXT    ENDS
  38. TSRgroup@
  39.  
  40. ;-----------------------------------------------------------------------
  41. ; Put the resident code into its own segment so that all the offsets are
  42. ; proper for the new location after copying it into a UMB or down into
  43. ; the PSP.
  44. ;
  45. TSRcode@
  46. start_TSRcode label byte
  47.  
  48. ;-----------------------------------------------------------------------
  49. ; Since we need a TSR, but might be loaded into a UMB or at the top of
  50. ; conventional memory, we make a copy of the all-important first 64 bytes
  51. ; of the PSP here.  After relocation, this copy will start at offset 0
  52. ;
  53. TSR_PSP    db 64 dup (?)
  54.  
  55. ;-----------------------------------------------------------------------
  56. ; TSR's initialized data storage
  57. ;
  58. TSRdata@
  59. TSR_name    db "NOTE",0
  60. int13_busy    db 0
  61. want_popup    db 0
  62. want_shutdown    db 0
  63. TSR_activated    db 0
  64. popup_INT28    db 0
  65.  
  66. ;;; add TSR-specific initialized data below
  67.  
  68. CRLF_buffer    db 13,10
  69.  
  70. TSRdataEnd@
  71.  
  72. ;-----------------------------------------------------------------------
  73. ; TSR's uninitialized data storage
  74. ;
  75. TSRbss@
  76. INDOS_ptr    dd ?
  77. CRITERR_ptr    dd ?
  78. interrupted_DTA    dd ?
  79. interrupted_PSP dw ?
  80. interrupted_SP    dw ?
  81. interrupted_SS    dw ?
  82.  
  83. interrupted_cursorpos dw ?
  84. display_page_attr label word
  85. display_attr    db ?
  86. display_page    db ?
  87. screen_width    db ?
  88.  
  89. cursor_pos label word
  90. cursor_x    db ?
  91. cursor_y    db ?
  92.  
  93. screen_buffer     db (WINDOW_HEIGHT*WINDOW_WIDTH*2) dup (?)
  94. local_stack     db LOCAL_STACK_SIZE dup (?)
  95. local_stack_bottom label byte
  96.  
  97. ;;; add TSR-specific uninitialized data below
  98.  
  99. notefile_handle dw ?
  100.  
  101. edit_buffer    db WINDOW_WIDTH-2 dup (?)
  102. TSRbssEnd@
  103.  
  104.  
  105. ;-----------------------------------------------------------------------
  106.  
  107. TSR_main proc near
  108.     ASSUME    DS:TGROUP,ES:NOTHING
  109.     xor    si,si            ; SI stores line length
  110. TSR_main_loop:
  111.     mov    dx,256*(WINDOW_TOP+1) + (WINDOW_LEFT+1)
  112.     add    dx,si
  113.     call    TSR_move_cursor
  114.     call    TSR_getkey
  115.     cmp    al,0Dh            ; Enter pressed?
  116.     je    TSR_main_line_end
  117.     cmp    al,27            ; Esc pressed?
  118.     je    TSR_main_done
  119.     cmp    al,8
  120.     je    backspace
  121.     cmp    al,0            ; extended ASCII?
  122.     je    TSR_main_loop        ; if yes, ignore
  123.     cmp    al,0E0h
  124.     jne    got_char
  125.     cmp    ah,0
  126.     jne    TSR_main_loop
  127. got_char:
  128.     cmp    si,WINDOW_WIDTH-2
  129.     jb    store_char
  130. beep:
  131.     mov    ax,0E07h        ; beep
  132.     int    10h
  133.     jmp    TSR_main_loop
  134. store_char:
  135.     mov    edit_buffer[si],al
  136.     inc    si            ; remember that we got another char
  137.     call    TSR_put_char
  138.     jmp    TSR_main_loop
  139.  
  140. backspace:
  141.     or    si,si
  142.     jz    beep
  143.     dec    si
  144.     mov    dx,256*(WINDOW_TOP+1) + (WINDOW_LEFT+1)
  145.     add    dx,si
  146.     call    TSR_move_cursor
  147.     mov    al,' '
  148.     call    TSR_put_char
  149.     jmp    TSR_main_loop
  150.  
  151. TSR_main_line_end:
  152.     mov    ah,40h
  153.     mov    bx,notefile_handle
  154.     mov    cx,si
  155.     mov    dx,offset TGROUP:edit_buffer
  156.     int    21h
  157.     mov    ah,40h
  158.     mov    cx,2
  159.     mov    dx,offset TGROUP:CRLF_buffer
  160.     int    21h
  161.     call    TSR_clear_window
  162.     jmp    TSR_main        ; restart for next line
  163.  
  164. TSR_main_done:
  165.     mov    bx,notefile_handle
  166.     mov    ah,45h            ; DUP handle
  167.     int    21h
  168.     jc    TSR_main_exit        ; quit now if unable to duplicate
  169.     mov    bx,ax
  170.     mov    ah,3Eh            ; close duplicate
  171.     int    21h
  172. TSR_main_exit:
  173.     ret
  174. TSR_main endp
  175.  
  176. ;-----------------------------------------------------------------------
  177. ; Function that performs any necessary cleanup prior to the TSR being
  178. ; removed from memory.  At the time it is called, the TSR is effectively
  179. ; popped up, though it has not modified the screen.  If this routine needs
  180. ; to write on the screen, it must save and restore the screen contents
  181. ; itself
  182. ;
  183. TSR_shutdown proc near
  184.     mov    bx,notefile_handle
  185.     mov    ah,3Eh            ; close the file
  186.     int    21h
  187.     ret
  188. TSR_shutdown endp
  189.  
  190. ;-----------------------------------------------------------------------
  191.  
  192. TSR_INT24_handler:
  193.     mov    al,03h            ; FAIL, for now
  194.     iret
  195.  
  196. ;-----------------------------------------------------------------------
  197. ; Simply ignore Ctrl-Break and Ctrl-C interrupts
  198. ;
  199. TSR_INT1B_handler:
  200. TSR_INT23_handler:
  201.     iret
  202.  
  203. ;=======================================================================
  204. ; It should not be necessary to make any changes between here and the
  205. ; end of the resident portion in order to modify this code for a different
  206. ; purpose.
  207. ;=======================================================================
  208.  
  209. ;-----------------------------------------------------------------------
  210. ;
  211. TSR_getkey proc near
  212.     mov    ah,11h            ; keystroke available?
  213.     int    16h
  214.     jnz    TSR_getkey_got_one    ; if yes, get it, otherwise
  215.     int    28h            ; give other TSRs a chance to do work
  216.     jmp    TSR_getkey
  217. TSR_getkey_got_one:
  218.     mov    ah,10h            ; get the keystroke
  219.     int    16h
  220.     ret
  221. TSR_getkey endp
  222.  
  223. ;-----------------------------------------------------------------------
  224. ; entry: DH = row, DL = column
  225. ;
  226. TSR_move_cursor proc near
  227.     ASSUME    DS:TGROUP,ES:NOTHING
  228.     mov    cursor_pos,dx
  229.     mov    bh,display_page
  230.     mov    ah,2            ; BIOS move-cursor function
  231.     int    10h
  232.     ret
  233. TSR_move_cursor endp
  234.  
  235. ;-----------------------------------------------------------------------
  236. ; entry: AL = char
  237. ; exit: AH,BX,CX,DX destroyed
  238. ;
  239. TSR_put_char proc near
  240.     mov    cx,1
  241.     ;; fall through to TSR_put_line
  242. TSR_put_char endp
  243.  
  244. ;-----------------------------------------------------------------------
  245. ; entry: AL = char, CX = repeat count
  246. ; exit: AX,BX,CX,DX destroyed
  247. ;
  248. TSR_put_line proc near
  249.     ASSUME    DS:TGROUP,ES:NOTHING
  250.     add    cursor_x,cl
  251.     mov    bx,display_page_attr
  252.     mov    ah,9
  253.     int    10h
  254.     mov    al,cursor_x
  255.     cmp    al,screen_width
  256.     jb    TSR_put_line_done
  257.     mov    cursor_x,0
  258.     inc    cursor_y
  259. ;
  260. ; need to handle case of falling off the bottom
  261. ;
  262.  
  263.  
  264. TSR_put_line_done:
  265.     mov    dx,cursor_pos
  266.     mov    ah,2            ; set cursor position
  267.     int    10h
  268.     ret
  269. TSR_put_line endp
  270.  
  271. ;-----------------------------------------------------------------------
  272.  
  273. save_screen proc near
  274.     ASSUME    DS:TGROUP,ES:NOTHING
  275.     mov    ah,0Fh
  276.     int    10h            ; get video mode and active page
  277.     mov    display_page,bh
  278.     mov    screen_width,ah
  279.     mov    ah,3            ; get cursor position on page BH
  280.     int    10h
  281.     mov    interrupted_cursorpos,dx
  282.     push    ds
  283.     pop    es
  284.     ASSUME    ES:TGROUP
  285.     mov    di,offset TGROUP:screen_buffer
  286.     mov    dh,WINDOW_TOP
  287. save_screen_loop1:
  288.     mov    dl,WINDOW_LEFT
  289. save_screen_loop2:
  290.     mov    ah,2            ; set cursor position on page BH
  291.     int    10h
  292.     mov    ah,8            ; read character&attribute on page BH
  293.     int    10h
  294.     stosw                ; and remember them for later restore
  295.     inc    dl
  296.     cmp    dl,WINDOW_LEFT+WINDOW_WIDTH
  297.     jb    save_screen_loop2
  298.     inc    dh
  299.     cmp    dh,WINDOW_TOP+WINDOW_HEIGHT
  300.     jb    save_screen_loop1
  301.     ret
  302. save_screen endp
  303.  
  304. ;-----------------------------------------------------------------------
  305.  
  306. framed_window proc near
  307.     ASSUME    DS:TGROUP,ES:NOTHING
  308.     mov    dx,256*WINDOW_TOP + WINDOW_LEFT
  309.     call    TSR_move_cursor
  310.     mov    display_attr,0Fh    ; bright white on black
  311.     mov    al,201            ; double upper left corner
  312.     call    TSR_put_char
  313.     mov    cx,WINDOW_WIDTH-2
  314.     mov    al,205
  315.     call    TSR_put_line
  316.     mov    al,187            ; double upper right corner
  317.     call    TSR_put_char
  318.     push    si
  319.     mov    dx,256*(WINDOW_TOP+1) + WINDOW_LEFT
  320. frame_loop:
  321.     mov    si,dx
  322.     call    TSR_move_cursor
  323.     mov    al,186            ; double vertical bar
  324.     call    TSR_put_char
  325.     mov    dx,si
  326.     mov    dl,WINDOW_LEFT+WINDOW_WIDTH-1
  327.     call    TSR_move_cursor
  328.     mov    al,186            ; double vertical bar
  329.     call    TSR_put_char
  330.     mov    dx,si
  331.     inc    dh
  332.     cmp    dh,WINDOW_TOP+WINDOW_HEIGHT-1
  333.     jb    frame_loop
  334.     pop    si
  335.     mov    dx,256*(WINDOW_TOP+WINDOW_HEIGHT-1) + WINDOW_LEFT
  336.     call    TSR_move_cursor
  337.     mov    display_attr,0Fh    ; bright white on black
  338.     mov    al,200            ; double lower left corner
  339.     call    TSR_put_char
  340.     mov    cx,WINDOW_WIDTH-2
  341.     mov    al,205
  342.     call    TSR_put_line
  343.     mov    al,188            ; double lower right corner
  344.     call    TSR_put_char
  345.     ;
  346.     ; frame is done, now add the title
  347.     ;
  348.     mov    dx,256*WINDOW_TOP + (WINDOW_LEFT+2)
  349.     call    TSR_move_cursor
  350.     mov    si,offset TGROUP:TSR_name
  351. frame_name_loop:
  352.     lodsb
  353.     or    al,al
  354.     jz    frame_name_done
  355.     call    TSR_put_char
  356.     jmp    frame_name_loop
  357. frame_name_done:
  358.     mov    dx,256*(WINDOW_TOP+1) + (WINDOW_LEFT+1)
  359.     call    TSR_move_cursor
  360.     mov    display_attr,07h    ; dim white on black
  361.     ;; fall through to TSR_clear_window ;;
  362. framed_window endp
  363.  
  364. ;-----------------------------------------------------------------------
  365.  
  366. TSR_clear_window proc near
  367.     mov    bh,display_attr
  368.     mov    cx,256*(WINDOW_TOP+1) + (WINDOW_LEFT+1)
  369.     mov    dx,256*(WINDOW_TOP+WINDOW_HEIGHT-2) + (WINDOW_LEFT+WINDOW_WIDTH-2)
  370.     mov    ax,0600h        ; clear popup window area
  371.     int    10h
  372.     ret
  373. TSR_clear_window endp
  374.  
  375. ;-----------------------------------------------------------------------
  376.  
  377. restore_screen proc near
  378.     ASSUME    DS:TGROUP,ES:NOTHING
  379.     mov    si,offset TGROUP:screen_buffer
  380.     mov    dh,WINDOW_TOP
  381. rest_screen_loop1:
  382.     mov    dl,WINDOW_LEFT
  383. rest_screen_loop2:
  384.     mov    ah,2
  385.     mov    bh,display_page
  386.     int    10h            ; set cursor position
  387.     lodsw                ; get character and attribute to restore
  388.     mov    bl,ah            ; BL <- attribute
  389.     mov    cx,1
  390.     mov    ah,9            ; write character&attribute
  391.     int    10h
  392.     inc    dl
  393.     cmp    dl,WINDOW_LEFT+WINDOW_WIDTH
  394.     jb    rest_screen_loop2
  395.     inc    dh
  396.     cmp    dh,WINDOW_TOP+WINDOW_HEIGHT
  397.     jb    rest_screen_loop1
  398.     mov    dx,interrupted_cursorpos
  399.     mov    ah,2            ; restore cursor position
  400.     int    10h
  401.     ret
  402. restore_screen endp
  403.  
  404. ;-----------------------------------------------------------------------
  405. ; requires DS = TGROUP and interrupts enabled on entry; may destroy BX
  406. ;
  407. popup proc near
  408.     mov    want_popup,0        ; we are finally popping up
  409.     mov    TSR_activated,1
  410.     ;
  411.     ; switch to a local stack so that we are assured of enough stack space
  412.     ;
  413.     push    ax
  414.     mov    interrupted_SS,ss
  415.     mov    interrupted_SP,sp
  416.     mov    ax,cs
  417.     cli
  418.     mov    ss,ax
  419.     ASSUME    SS:TGROUP
  420.     mov    sp,offset RESIDENT_CODE:local_stack_bottom
  421.     sti
  422.     push    es
  423.     push    di
  424.     push    si
  425.     push    bp
  426.     push    dx
  427.     push    cx
  428.     push    bx
  429.     ;
  430.     ; switch to our own PSP and store current DTA
  431.     ;
  432.     mov    ah,51h
  433.     int    21h
  434.     mov    interrupted_PSP,bx
  435.     mov    bx,cs
  436.     mov    ah,50h
  437.     int    21h
  438.     mov    ah,2Fh            ; get DTA
  439.     int    21h
  440.     ASSUME    ES:NOTHING
  441.     mov    word ptr interrupted_DTA,bx
  442.     mov    word ptr interrupted_DTA+2,es
  443.     GRAB_INTERRUPT 1Bh,TSR_INT1B_handler
  444.     GRAB_INTERRUPT 23h,TSR_INT23_handler
  445.     GRAB_INTERRUPT 24h,TSR_INT24_handler
  446.     mov    al,0
  447.     xchg    al,want_shutdown    ; get and clear shutdown flag
  448.     or    al,al            ; was it set?
  449.     jz    do_popup        ; if not, regular popup
  450.     call    TSR_shutdown
  451.     jmp short popup_done
  452. do_popup:
  453.     call    save_screen
  454.     call    framed_window
  455.     call    TSR_main        ; the actual guts of the TSR
  456.     call    restore_screen
  457. popup_done:
  458.     RESTORE_INTERRUPT 1Bh
  459.     RESTORE_INTERRUPT 23h
  460.     RESTORE_INTERRUPT 24h
  461.     ;
  462.     ; restore the original PSP and DTA
  463.     ;
  464.     mov    bx,interrupted_PSP
  465.     mov    ah,50h
  466.     int    21h
  467.     push    ds
  468.     lds    dx,interrupted_DTA
  469.     ASSUME    DS:NOTHING
  470.     mov    ah,1Ah
  471.     int    21h
  472.     pop    ds
  473.     ASSUME    DS:TGROUP
  474.     pop    bx
  475.     pop    cx
  476.     pop    dx
  477.     pop    bp
  478.     pop    si
  479.     pop    di
  480.     pop    es
  481.     ;
  482.     ; finally, switch back to original stack
  483.     ;
  484.     cli
  485.     mov    ss,interrupted_SS
  486.     ASSUME    SS:NOTHING
  487.     mov    sp,interrupted_SP
  488.     sti
  489.     mov    TSR_activated,0        ; no longer popped up, so OK to pop again
  490.     pop    ax
  491.     ret
  492. popup endp
  493.  
  494. ;-----------------------------------------------------------------------
  495.  
  496. attempt_popup proc near
  497.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  498.     mov    want_popup,1        ; remember that a popup was requested
  499.     ;; fall through to try_popup ;;
  500. attempt_popup endp
  501.  
  502. try_popup proc near
  503.     pushf
  504.     sti                ; OK to interrupt
  505.     cmp    int13_busy,0
  506.     jnz    try_popup_done
  507.     cmp    TSR_activated,0
  508.     jnz    try_popup_done
  509.     push    ds
  510.     push    bx
  511.     lds    bx,INDOS_ptr
  512.     ASSUME    DS:NOTHING
  513.     cmp    byte ptr [bx],1
  514.     jb    try_popup_1
  515.     ja    try_popup_2
  516.     cmp    popup_INT28,0        ; if activated via INT 28, INDOS flag is
  517.     jz    try_popup_2        ; allowed to be 1 rather than 0
  518. try_popup_1:
  519.     lds    bx,CRITERR_ptr
  520.     ASSUME    DS:NOTHING
  521.     cmp    byte ptr [bx],0
  522.     jne    try_popup_2
  523.     push    cs
  524.     pop    ds
  525.     ASSUME    DS:TGROUP
  526.     call    popup
  527. try_popup_2:
  528.     ASSUME    DS:NOTHING
  529.     pop    bx
  530.     pop    ds
  531.     ASSUME    DS:NOTHING
  532. try_popup_done:
  533.     popf
  534.     ret
  535. try_popup endp
  536.  
  537. ;-----------------------------------------------------------------------
  538.  
  539. API_popup proc near
  540.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  541.     call    attempt_popup
  542.     mov    al,AMIS_POPUP_WILLDO    ; can't pop up now, will do so when able
  543.     cmp    want_popup,1        ; did we manage to pop up?
  544.     je    API_popup_done
  545.     mov    al,AMIS_SUCCESSFUL    ; successful
  546.     xor    bx,bx            ; no return code
  547. API_popup_done:
  548.     ret
  549. API_popup endp
  550.  
  551. ;-----------------------------------------------------------------------
  552.  
  553. remov proc near
  554.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  555.     inc    want_shutdown
  556.     call    try_popup
  557.     mov    al,0
  558.     xchg    al,want_shutdown    ; get and clear shutdown flag
  559.     cmp    al,0            ; if no longer set, shutdown successful
  560.     je    remov_successful
  561.     mov    al,AMIS_UNINST_TRYLATER
  562.     ret
  563. remov_successful:
  564.     mov    al,AMIS_UNINST_SAFE_OFF ; no resident remover, now disabled
  565.     mov    bx,0            ; seg of block to free (will be patched)
  566. ALTMPX$PSP equ word ptr ($-2)        ; magic name of word to be patched with
  567.                     ; actual memory block segment by TSR
  568.                     ; installation code
  569.     ret
  570. remov endp
  571.  
  572. ;-----------------------------------------------------------------------
  573. ; Declare the interrupt vectors hooked by the program, then set up the
  574. ; Alternate Multiplex Interrupt Spec handler
  575. ;
  576.     HOOKED_INTS 13h,15h,21h,28h
  577.     ALTMPX    'Ralf B','NOTE',VERSION_NUM,"Append notes to a file",,,API_popup,remov,Y
  578.  
  579. ;-----------------------------------------------------------------------
  580. ; Can't pop up when disk is busy, so try to pop up on return
  581. ; We can save one byte by specifying the hardware reset handler set up by
  582. ; the ALTMPX macro above
  583. ;
  584. int13_handler proc far
  585. ISP_HEADER 13h,hw_reset_2Dh
  586.     pushf
  587.     inc    int13_busy
  588.     call    ORIG_INT13h
  589.     pushf
  590.     dec    int13_busy
  591.     cmp    want_popup,0
  592.     je    int13_done
  593.     call    try_popup
  594. int13_done:
  595.     popf
  596.     ret    2
  597. int13_handler endp
  598.  
  599. ;-----------------------------------------------------------------------
  600. ; Hotkey checker.  Hotkey is Shift+Shift+Key, where Key is patched in at
  601. ; installation.
  602. ;
  603. int15_handler proc far
  604. ISP_HEADER 15h
  605.     jnc    int15_done
  606.     pushf
  607.     sti
  608.     cmp    ax,4F00h+HOTKEY_SCAN    ; can also patch with actual scan code
  609. hotkey_scancode equ byte ptr ($-2)    ;   at installation time
  610.     jne    not_hotkey
  611.     cmp    TSR_activated,0
  612.     jne    not_hotkey        ; ignore hotkey if already popped up
  613.     push    ds
  614.     push    ax
  615.     xor    ax,ax
  616.     mov    ds,ax
  617.     mov    al,ds:[417h]        ; get shift states
  618.     and    al,3            ; Shift+Shift
  619.     cmp    al,3            ; both pressed?
  620.     pop    ax
  621.     pop    ds
  622.     jne    not_hotkey
  623.     ;
  624.     ; yes, we got our hotkey
  625.     ;
  626.     call    attempt_popup
  627.     popf
  628.     clc                ; throw out scan code
  629.     ret    2
  630. not_hotkey:
  631.     popf
  632. int15_done:
  633.     jmp    ORIG_INT15h
  634. int15_handler endp
  635.  
  636. ;-----------------------------------------------------------------------
  637. ; Can't pop up when DOS is busy, so try to pop up on return
  638. ;
  639. int21_handler proc far
  640. ISP_HEADER 21h
  641.     pushf
  642.     call    ORIG_INT21h
  643.     pushf
  644.     sti
  645.     cmp    want_popup,0
  646.     je    int21_done
  647.     call    try_popup
  648. int21_done:
  649.     popf
  650.     ret    2
  651. int21_handler endp
  652.  
  653. ;-----------------------------------------------------------------------
  654. ; Can't pop up when DOS is busy, but can do so during an INT 28h
  655. ;
  656. ISP_HEADER 28h
  657.     sti
  658.     cmp    want_popup,0
  659.     je    int28_done
  660.     inc    popup_INT28
  661.     call    try_popup
  662.     dec    popup_INT28
  663. int28_done:
  664.     jmp    ORIG_INT28h
  665.  
  666. ;-----------------------------------------------------------------------
  667.  
  668. resident_code_end label byte
  669. TSRcodeEnd@
  670.  
  671. TSRdata@
  672. resident_data_end label byte
  673. TSRdataEnd@
  674.  
  675. TSRbss@
  676. resident_bss_end label byte
  677. TSRbssEnd@
  678.  
  679. resident_code_size equ offset TGROUP:resident_bss_end
  680.  
  681. ;-----------------------------------------------------------------------
  682.  
  683. _TEXT SEGMENT 'CODE'
  684.     ASSUME cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
  685.     ORG 100h
  686.  
  687. NOTE:
  688.     DISPLAY_STRING banner
  689.     CHECK_DOS_VER 3,00        ; we use features not available in 2.x
  690.     mov    bx,1000h        ; set memory block to 64K
  691.     mov    ah,4Ah
  692.     int    21h
  693.     mov    si,81h            ; SI -> command line
  694.     cld                ; ensure proper direction for string ops
  695. cmdline_loop:
  696.     lodsb
  697.     cmp    al,' '            ; skip blanks and tabs on commandline
  698.     je    cmdline_loop
  699.     cmp    al,9
  700.     je    cmdline_loop
  701.     cmp    al,'-'
  702.     je    got_cmdline_switch
  703. bad_cmdline:
  704.     jmp    usage
  705. got_cmdline_switch:
  706.     lodsb                ; get next character
  707.     and    al,0DFh            ; force to uppercase
  708.     cmp    al,'R'
  709.     jne    not_removing
  710.     jmp    removing
  711. not_removing:
  712.     cmp    al,'I'
  713.     jne    bad_cmdline
  714. installing:
  715.     ;
  716.     ; place any necessary pre-initialization here
  717.     ;
  718.     mov    dx,si            ; point at filename
  719.     mov    filename_start,si
  720. scan_filename_loop:
  721.     lodsb
  722.     cmp    al,' '
  723.     ja    scan_filename_loop
  724.     mov    byte ptr [si-1],0    ; turn filename into ASCIZ
  725.     mov    ax,3DC1h        ; open, no-inherit/DENYNONE/write-only
  726.     int    21h
  727.     jnc    open_successful
  728.     mov    ax,3C00h        ; if unable to open, try creating file
  729.     int    21h
  730.     jnc    create_successful
  731.     jmp    open_failed
  732. open_successful:
  733. create_successful:
  734.     mov    bx,ax
  735.     mov    ah,3Eh            ; close the file again; we now know
  736.     int    21h            ;   we can access it
  737.     ;
  738.     ; find out whether keyboard intercept is available
  739.     ;
  740.     stc
  741.     mov    ah,0C0h
  742.     int    15h            ; get ROM BIOS configuration data
  743.     ASSUME    ES:NOTHING
  744.     mov    dx,offset _TEXT:no_hotkey_msg
  745.     jc    no_kbd_intercept
  746.     test    byte ptr es:[bx+5],10h    ; have keyboard intercept?
  747.     jz    no_kbd_intercept
  748.     mov    dx,offset _TEXT:hotkey_msg
  749. no_kbd_intercept:
  750.     mov    ah,9
  751.     int    21h
  752.     ;
  753.     ; get and store pointers to DOS busy flags
  754.     ;
  755.     mov    ah,34h
  756.     int    21h
  757.     ASSUME    ES:NOTHING
  758.     mov    word ptr _TEXT:INDOS_ptr,bx
  759.     mov    word ptr _TEXT:INDOS_ptr+2,es
  760.     push    ds
  761.     mov    ax,5D06h
  762.     int    21h
  763.     ASSUME    DS:NOTHING
  764.     mov    word ptr _TEXT:CRITERR_ptr+2,ds
  765.     pop    ds
  766.     ASSUME    DS:_TEXT
  767.         mov     word ptr _TEXT:CRITERR_ptr,si
  768.     ;
  769.     ; now go install the TSR
  770.     ;
  771.     INSTALL_TSR <offset _TEXT:start_TSRcode>,RELBYTE,resident_code_size,BYTE,,BEST,TOPMEM,inst_patch,already_installed
  772.  
  773. removing:
  774.     UNINSTALL <offset _TEXT:start_TSRcode>,RELBYTE,cant_uninstall
  775.     push    cs
  776.     pop    ds
  777.     DISPLAY_STRING uninstalled_msg
  778.         mov     ax,4C00h
  779.     int    21h
  780.  
  781. already_installed:
  782.     mov    dx,offset _TEXT:already_inst_msg
  783.     jmp short exit_with_error
  784.  
  785. open_failed:
  786.     mov    dx,offset _TEXT:cant_access_msg
  787.     jmp short exit_with_error
  788. usage:
  789.     mov    dx,offset _TEXT:usage_msg
  790.     jmp short exit_with_error
  791.  
  792. cant_uninstall:
  793.     mov    dx,offset _TEXT:cant_remove_msg
  794. exit_with_error:
  795.     mov    ah,9
  796.     int    21h
  797.     mov    ax,4C01h
  798.     int    21h
  799.  
  800. inst_patch:
  801.     push    ax            ; remember resident segment
  802.     DISPLAY_STRING installed_msg
  803.         pop     ax                      ; get back resident segment
  804.         push    es
  805.         mov     es,ax
  806.     ASSUME    ES:TGROUP
  807.     ;
  808.     ; close all files which will not be used by the TSR
  809.     ;
  810.     mov    bx,0            ; for this TSR, don't need handles 0-4
  811. close_file_loop:
  812.     mov    ah,3Eh
  813.     int    21h
  814.     inc    bx
  815.     cmp    bx,4
  816.     jbe    close_file_loop
  817.     ;
  818.     ; now copy the PSP into the resident portion
  819.     ;
  820.     xor    si,si
  821.     xor    di,di
  822.     mov    cx,size TSR_PSP
  823.     cld
  824.     rep    movsb
  825.     mov    es:[36h],es        ; adjust JFT pointer in copied PSP
  826.     mov    bx,es
  827.     mov    ah,50h            ; set PSP segment so TSR owns file
  828.     int    21h
  829.     push    cs
  830.     pop    ds
  831.     ASSUME    DS:_TEXT
  832.     mov    dx,filename_start
  833.         mov     ax,3DC1h                ; open, no-inherit/DENYNONE/write-only
  834.     int    21h
  835.     jnc    reopen_successful
  836.     xor    ax,ax            ; point at a closed handle
  837. reopen_successful:
  838.     mov    TGROUP:notefile_handle,ax
  839.     mov    bx,ax
  840.     xor    cx,cx
  841.     xor    dx,dx
  842.     mov    ax,4202h        ; position to end of file
  843.     int    21h
  844.     mov    ah,50h            ; restore PSP segment
  845.     mov    bx,cs
  846.     int    21h
  847.     ;
  848.     ; finally, zero out the JFT in our PSP so that the exit won't close
  849.     ; the files that the TSR does need
  850.     ;
  851.     les    di,cs:[0034h]        ; pointer to JFT
  852.     mov    cx,cs:[0032h]        ; size of JFT
  853.     mov    al,0FFh            ; closed-file flag
  854.     rep    stosb
  855.     pop    es
  856.     ASSUME    ES:NOTHING
  857.     ret
  858.  
  859. banner     db 'NOTE v',VERSION_STR,'  Public Domain 1992 Ralf Brown',13,10,'$'
  860. usage_msg     db "Usage:",9,"NOTE -Ifile",9,"Install using <file> as notepad",13,10
  861.          db 9,"NOTE -R",9,9,"Remove from memory",13,10
  862.          db "$"
  863. hotkey_msg     db "Press Shift-Shift-",HOTKEY_NAME," to pop up",13,10,"$"
  864. no_hotkey_msg     db "Hotkey is not available on this machine",13,10,"$"
  865. installed_msg     db "Installed.",13,10,"$"
  866. already_inst_msg db 13,10,"Already installed.",13,10,"$"
  867. cant_remove_msg  db "Can't remove from memory.",13,10,"$"
  868. uninstalled_msg  db "Removed.",13,10,"$"
  869. cant_access_msg     db "Unable to open or create notepad file",13,10,"$"
  870.  
  871. filename_start     dw ?
  872. _TEXT ENDS
  873.  
  874.      end NOTE
  875.  
  876.